package org.firebug.common.tools.core;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Author: 张晓东
 */
public final class DateTools {
    public static final long MILLIS_OF_DAY = 24 * 60 * 60 * 1000;
    public static final String YMD = "yyyy-MM-dd";
    public static final String YMDHMS = "yyyy-MM-dd HH:mm:ss";

    public static String format(Date date) {
        return new SimpleDateFormat(YMDHMS).format(date);
    }

    public static String format(Date date, String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }

    public static Date parse(String date) throws ParseException {
        return new SimpleDateFormat(YMDHMS).parse(date);
    }

    public static Date parse(String date, String pattern) throws ParseException {
        return new SimpleDateFormat(pattern).parse(date);
    }

    public static void offset(Date date, long millis) {
        date.setTime(date.getTime() + millis);
    }

    public static void clearTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date.getTime());
        calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMinimum(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE, calendar.getActualMinimum(Calendar.MINUTE));
        calendar.set(Calendar.SECOND, calendar.getActualMinimum(Calendar.SECOND));
        calendar.set(Calendar.MILLISECOND, calendar.getActualMinimum(Calendar.MILLISECOND));
        date.setTime(calendar.getTimeInMillis());
    }

    /**
     * 上边界(天)：yyyy-MM-dd 00:00:00.000
     */
    public static long upperOfDay(Date date) {
        return upperOfDay(date.getTime());
    }
    public static long upperOfDay(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return upperOfDay(calendar).getTimeInMillis();
    }
    public static Calendar upperOfDay(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMinimum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMinimum(Calendar.MINUTE));
        temp.set(Calendar.SECOND, temp.getActualMinimum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND, temp.getActualMinimum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 下边界(天)：yyyy-MM-dd 23:59:59.999
     */
    public static long lowerOfDay(Date date) {
        return lowerOfDay(date.getTime());
    }
    public static long lowerOfDay(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return lowerOfDay(calendar).getTimeInMillis();
    }
    public static Calendar lowerOfDay(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 上边界(周)：yyyy-MM-dd(周日) 00:00:00.000
     */
    public static long upperOfWeek(Date date) {
        return upperOfWeek(date.getTime());
    }
    public static long upperOfWeek(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return upperOfWeek(calendar).getTimeInMillis();
    }
    public static Calendar upperOfWeek(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getActualMinimum(Calendar.DAY_OF_WEEK));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMinimum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMinimum(Calendar.MINUTE));
        temp.set(Calendar.SECOND, temp.getActualMinimum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND, temp.getActualMinimum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 下边界(周)：yyyy-MM-dd(周六) 23:59:59.999
     */
    public static long lowerOfWeek(Date date) {
        return lowerOfWeek(date.getTime());
    }
    public static long lowerOfWeek(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return lowerOfWeek(calendar).getTimeInMillis();
    }
    public static Calendar lowerOfWeek(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.DAY_OF_WEEK, temp.getActualMaximum(Calendar.DAY_OF_WEEK));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 上边界(月)：yyyy-MM-01 00:00:00.000
     */
    public static long upperOfMonth(Date date) {
        return upperOfMonth(date.getTime());
    }
    public static long upperOfMonth(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return upperOfMonth(calendar).getTimeInMillis();
    }
    public static Calendar upperOfMonth(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMinimum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMinimum(Calendar.MINUTE));
        temp.set(Calendar.SECOND, temp.getActualMinimum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND, temp.getActualMinimum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 下边界(月)：yyyy-MM-(28|29|30|31) 23:59:59.999
     */
    public static long lowerOfMonth(Date date) {
        return lowerOfMonth(date.getTime());
    }
    public static long lowerOfMonth(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return lowerOfMonth(calendar).getTimeInMillis();
    }
    public static Calendar lowerOfMonth(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 上边界(季)：yyyy-(01|04|07|10)-01 00:00:00.000
     */
    public static long upperOfQuarter(Date date) {
        return upperOfQuarter(date.getTime());
    }
    public static long upperOfQuarter(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return upperOfQuarter(calendar).getTimeInMillis();
    }
    public static Calendar upperOfQuarter(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        int month = temp.get(Calendar.MONTH);
        if(month == Calendar.JANUARY || month == Calendar.FEBRUARY || month == Calendar.MARCH) {
            temp.set(Calendar.MONTH, Calendar.JANUARY);
        } else if(month == Calendar.APRIL || month == Calendar.MAY || month == Calendar.JUNE) {
            temp.set(Calendar.MONTH, Calendar.APRIL);
        } else if(month == Calendar.JULY || month == Calendar.AUGUST || month == Calendar.SEPTEMBER) {
            temp.set(Calendar.MONTH, Calendar.JULY);
        } else if(month == Calendar.OCTOBER || month == Calendar.NOVEMBER || month == Calendar.DECEMBER) {
            temp.set(Calendar.MONTH, Calendar.OCTOBER);
        }
        temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 下边界(季)：yyyy-(03|06|09|12)-(31|30|30|31) 23:59:59.999
     */
    public static long lowerOfQuarter(Date date) {
        return lowerOfQuarter(date.getTime());
    }
    public static long lowerOfQuarter(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return lowerOfQuarter(calendar).getTimeInMillis();
    }
    public static Calendar lowerOfQuarter(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        int month = temp.get(Calendar.MONTH);
        if(month == Calendar.JANUARY || month == Calendar.FEBRUARY || month == Calendar.MARCH) {
            temp.set(Calendar.MONTH, Calendar.MARCH);
        } else if(month == Calendar.APRIL || month == Calendar.MAY || month == Calendar.JUNE) {
            temp.set(Calendar.MONTH, Calendar.JUNE);
        } else if(month == Calendar.JULY || month == Calendar.AUGUST || month == Calendar.SEPTEMBER) {
            temp.set(Calendar.MONTH, Calendar.SEPTEMBER);
        } else if(month == Calendar.OCTOBER || month == Calendar.NOVEMBER || month == Calendar.DECEMBER) {
            temp.set(Calendar.MONTH, Calendar.DECEMBER);
        }
        temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 上边界(年)：yyyy-01-01 00:00:00.000
     */
    public static long upperOfYear(Date date) {
        return upperOfYear(date.getTime());
    }
    public static long upperOfYear(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return upperOfYear(calendar).getTimeInMillis();
    }
    public static Calendar upperOfYear(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.MONTH, Calendar.JANUARY);
        temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    /**
     * 下边界(年)：yyyy-12-31 23:59:59.999
     */
    public static long lowerOfYear(Date date) {
        return lowerOfYear(date.getTime());
    }
    public static long lowerOfYear(long millis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        return lowerOfYear(calendar).getTimeInMillis();
    }
    public static Calendar lowerOfYear(Calendar calendar) {
        Calendar temp = (Calendar) calendar.clone();
        temp.set(Calendar.MONTH, Calendar.DECEMBER);
        temp.set(Calendar.DAY_OF_MONTH, temp.getActualMaximum(Calendar.DAY_OF_MONTH));
        temp.set(Calendar.HOUR_OF_DAY, temp.getActualMaximum(Calendar.HOUR_OF_DAY));
        temp.set(Calendar.MINUTE, temp.getActualMaximum(Calendar.MINUTE));
        temp.set(Calendar.SECOND,temp.getActualMaximum(Calendar.SECOND));
        temp.set(Calendar.MILLISECOND,temp.getActualMaximum(Calendar.MILLISECOND));
        return temp;
    }

    private DateTools () {
    }
}
